function mouse2Game(x: number, y: number, obj: egret.DisplayObject): [number, number] {
	// let canvas = window.document.getElementById("gameDiv")
	const canvas = document.getElementsByTagName('CANVAS')[0];
	const style = window.getComputedStyle(canvas, null);
	const rect = canvas.getBoundingClientRect();
	const w = obj.width;
	const h = obj.height;

	// console.log(x,y,style["width"],style["height"],rect,w,h)
	return [
		Math.floor((x - rect.left) * (w / rect.width)), // 全局坐标*水平方向的缩放因子
		Math.floor((y - rect.top) * (h / rect.height)),
	];
}

function mouse2GamePoint(x: number, y: number, obj: egret.DisplayObject): egret.Point {
	const [x2, y2] = mouse2Game(x, y, obj);
	return new egret.Point(x, y);
}

function safeRemoveFromFather(child: egret.DisplayObject): void {
	if (child && child.parent) {
		child.parent.removeChild(child);
	}
}

function isSelfOrParent(child: egret.DisplayObject, parent: egret.DisplayObject): boolean {
	return child === parent || isOldParent(child, parent);
}

// 祖先
function isOldParent(child: egret.DisplayObject, parent: egret.DisplayObject): boolean {
	if (!child) {
		return false;
	}
	let p = child.parent;
	while (p) {
		if (p === parent) {
			return true;
		}
		p = p.parent;
	}
	return false;
}

function removeAllEventListener(obj: egret.DisplayObject): void {
	// console.log("removeAllEventListener",obj.name)
	obj.$EventDispatcher = {
		0: obj,
		1: {},
		2: {},
		3: 0,
	};
}

function releaseContainer(obj: egret.DisplayObjectContainer): void {
	// 保证先remove在release!
	removeAllEventListener(obj);
	const childs = [...obj.$children];
	obj.removeChildren();
	for (const child of childs) {
		// if (child instanceof westMC)
		//	child.stop()
		// eslint-disable-next-line dot-notation
		if (child['release']) {
			// eslint-disable-next-line dot-notation
			child['release']();
		}
		removeAllEventListener(child);
		if (child instanceof egret.DisplayObjectContainer) {
			releaseContainer(child);
		}
	}
}

function fullAlign(obj: eui.UIComponent): void {
	obj.left = 0;
	obj.right = 0;
	obj.top = 0;
	obj.bottom = 0;
}

function allCenter(obj: eui.UIComponent): void {
	obj.verticalCenter = 0;
	obj.horizontalCenter = 0;
}

function FitSize(obj: egret.DisplayObject, w: number, h: number) {
	const sw = obj.width / w;
	const sh = obj.height / h;
	if (sw > sh) {
		obj.scaleX = 1 / sw;
		obj.scaleY = 1 / sw;
	} else {
		obj.scaleX = 1 / sh;
		obj.scaleY = 1 / sh;
	}
}

function toggleVisible(obj: egret.DisplayObject): void {
	obj.visible = !obj.visible;
}

function mouseScrollSlider(vs: eui.VSlider): void {
	vs.track.addEventListener(
		mouse.MouseEvent.MOUSE_WHEEL,
		(ev: egret.Event) => {
			const deltaY = ev.data;
			vs.value += deltaY / -10;
			vs.value = Math.limit(vs.value, vs.minimum, vs.maximum);
			vs.dispatchEventWith(egret.Event.CHANGE);
		},
		null,
	);
	vs.thumb.addEventListener(
		mouse.MouseEvent.MOUSE_WHEEL,
		(ev: egret.Event) => {
			const deltaY = ev.data;
			vs.value += deltaY / -10;
			vs.value = Math.limit(vs.value, vs.minimum, vs.maximum);
			vs.dispatchEventWith(egret.Event.CHANGE);
		},
		null,
	);
}

function isNumber(n: number) {
	return typeof n === 'number' && !Number.isNaN(n);
}

interface iPos {
	x: number;
	y: number;
}

function assertObjPos(obj: iPos): void {
	assert(isNumber(obj.x));
	assert(isNumber(obj.y));
}

function assertNumber(a: number): void {
	assert(isNumber(a));
}

function assertNumbers(a: number[]): void {
	for (const n of a) {
		assertNumber(n);
	}
}

function CraeteBgRect(f: eui.Component, cr = 0, alpha = 0.5) {
	const r = new eui.Rect(0, 0, cr);
	fullAlign(r);
	f.addChildAt(r, 0);
	r.alpha = alpha;
	return r;
}

function keepChildOrder(
	f: egret.DisplayObjectContainer,
	c1: egret.DisplayObject,
	c2: egret.DisplayObject,
) {
	if (!c1 || !c2) {
		return;
	}
	const i1 = f.getChildIndex(c1);
	const i2 = f.getChildIndex(c2);
	if (i1 >= 0 && i2 >= 0) {
		if (i1 > i2) {
			f.swapChildrenAt(i1, i2);
		}
	}
}

interface ShakeObj extends egret.DisplayObject {
	isShaking: boolean;
	align: Object;
}

function shakeObj(
	_obj: egret.DisplayObject,
	time: number,
	disx: number,
	disy: number,
	disx2: number,
	disy2: number,
	callback: dramaCallback = null,
): void {
	const obj = _obj as ShakeObj;
	if (obj.isShaking) {
		if (callback) {
			callback(0);
		}
		return;
	}

	const { x, y } = obj;
	if (obj instanceof eui.Component) {
		obj.align = saveAlign(obj);
		clearAlign(obj);
		// 必须重设size，否则会用编辑器的1280*720作为w,h
		obj.width = obj.width;
		obj.height = obj.height;
	}

	obj.isShaking = true;
	const tw = egret.Tween.get(obj);
	tw.to({ x: x + disx, y: y + disy }, time, egret.Ease.bounceOut)
		.to({ x: x + disx2, y: y + disy2 }, time, egret.Ease.bounceOut)
		.to({ x: x + disx / 2, y: y + disy / 2 }, time / 2, egret.Ease.bounceOut)
		.to({ x: x + disx2 / 2, y: y + disy2 / 2 }, time / 2, egret.Ease.bounceOut)
		.to({ x: x + disx / 4, y: y + disy / 4 }, time / 4, egret.Ease.bounceIn)
		.to({ x: x + disx2 / 4, y: y + disy2 / 4 }, time / 4, egret.Ease.bounceIn)
		.call(() => {
			if (obj instanceof eui.Component) {
				restoreAlign(obj, obj.align);
				obj.align = null;
			}
			obj.isShaking = false;
			if (callback) {
				callback(1);
			}
		});
}

async function showTextOneByOne(lb: eui.Label, s: string, wait: number) {
	for (let i = 1; i <= s.length; i++) {
		lb.text = s.substring(0, i);
		await waitMs(wait);
	}
}
